package com.ming.transaction.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ming.transaction.common.MD5Util;
import com.ming.transaction.common.Result;
import com.ming.transaction.entity.Dto.LoAndRiDto;
import com.ming.transaction.entity.Dto.PassWordDto;
import com.ming.transaction.entity.Image;
import com.ming.transaction.entity.Menu;
import com.ming.transaction.entity.User;
import com.ming.transaction.exception.ServiceException;
import com.ming.transaction.mapper.MenuMapper;
import com.ming.transaction.mapper.RoleMapper;
import com.ming.transaction.mapper.RoleMenuMapper;
import com.ming.transaction.mapper.UserMapper;
import com.ming.transaction.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ming.transaction.util.jwtTokenUtil;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static com.ming.transaction.common.Constant.*;

/**
 * <p>
 * 用户登录注册类
 * </p>
 *
 * @author 陈仕健
 * @since 2023-04-27
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private HttpServletRequest request;

    @Resource
    private HttpServletResponse response;

    @Resource
    private RoleMapper roleMapper;

    @Autowired
    private jwtTokenUtil TokenUtil;

    @Resource
    private RoleMenuMapper roleMenuMapper;

    @Resource
    private MenuServiceImpl menuService;

    @Value("${files.uuload.path}")
    private String fileULoadPath;

    /**
     * 用户登录 Or 注册
     *
     * @param loAndRiDto
     * @return
     */
    @Override
    public Result loginRig(LoAndRiDto loAndRiDto) {
        String kaptcha = (String) request.getSession().getAttribute("kaptcha");
        if (StringUtils.isEmpty(loAndRiDto.getCode()) || !kaptcha.equalsIgnoreCase(loAndRiDto.getCode())) {
            return Result.fail("验证码输入错误，请重新输入!");
        }

        // 1.查询数据库是否存在该用户
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("number", loAndRiDto.getNumber());
        // 2. 用户查询
        User user = getOne(queryWrapper);
        // 2.1 用户不存在 插入数据
        // 前端规定一定需要插入数值 剔除空数据插入
        if (user == null) {
            User users = new User();
            users.setNumber(loAndRiDto.getNumber());
            users.setPassword(MD5Util.inputPassToFormPass(loAndRiDto.getPassword()));
            // 注册生成默认用户名
            users.setNickname("user_" + RandomUtil.randomNumbers(6));
            // 注册直接为普通用户
            users.setRole(ROLE_USER);
            users.setIcon(USER_PICTURE);
            save(users);
            return Result.success("用户注册成功,直接登录!!", logRiToken(users));
        }

        // 3.如果用户不为空 则比对密码
        queryWrapper.eq("password", MD5Util.inputPassToFormPass(loAndRiDto.getPassword()));
        // 4. 获取用户
        user = getOne(queryWrapper);
        if (user == null) {
            return Result.fail("用户密码错误！！");
        }
        // 4.1 登录并获取 Token
        return Result.success("用户登录成功！！", logRiToken(user));
    }

    /**
     * 封装登录或注册/ 获取角色菜单 / 返回 Token
     * @param user
     * @return
     */
    public LoAndRiDto logRiToken(User user){
        LoAndRiDto userDto = BeanUtil.copyProperties(user, LoAndRiDto.class);

        // 获取菜单
        Integer roleId = roleMapper.selectByFlag(userDto.getRole());
        List<Integer> menuIds = roleMenuMapper.selectByRoleId(roleId);
        List<Menu> list = menuService.findAll();

        // new 最后赛选完成之后的 list
        List<Menu> roleMenus = new ArrayList<>();
        //筛选当前用户角色菜单
        for (Menu menu : list) {
            if (menuIds.contains(menu.getId())){
                roleMenus.add(menu);
            }
            List<Menu> children = menu.getChildren();
            children.removeIf(child -> !menuIds.contains(child.getId()));
        }
        userDto.setMenus(roleMenus);
        userDto.setToken(TokenUtil.generateToken(user.getNumber()));
        request.getSession().setAttribute("Number", user.getNumber());
        request.getSession().setAttribute("ROLE",user.getRole());
        return userDto;
    }

    /**
     * 管理员添加用户
     *
     * @param user
     * @return
     */
    @Override
    public Result addUser(User user) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("number", user.getNumber());
        User users = getOne(queryWrapper);
        if (users != null) {
            throw new ServiceException(500, "用户已存在，不能添加!");
        }
        if (user.getNumber().length() < 8 &&
                user.getNumber().length() > 12) {
            throw new ServiceException(500, "账号输入格式不正确!");
        }
        if (user.getNickname() == null) {
            user.setNickname("user_" + RandomUtil.randomNumbers(6));
        }
        if (save(user)) {
            return Result.success("用户添加成功!");
        }
        return Result.fail(500,"用户添加失败!");
    }

    /**
     * 修改用户信息
     * @param user
     * @return
     */
    @Override
    public Result editUser(User user) {
        if (saveOrUpdate(user)) {
            return Result.success("用户修改成功!");
        }
        return Result.fail(500,"用户修改失败!");
    }

    /**
     * 用户头像上传
     * @param file
     * @return
     * @throws IOException
     */
    @Override
    public Result uploadImage(MultipartFile file) throws IOException {
        // 获取文件名称
        String originalFilename = file.getOriginalFilename();
        // 获取文件类型
        String type = FileUtil.extName(originalFilename);
        if (!Filetype(type)) {
            throw new ServiceException(405, "图片格式不正确!");
        }
        // 文件存储到磁盘
        File uploadParentFile = new File(fileULoadPath);
        // 判断配置的文件目录是否存在，若不存在则创建一个新的文件目录
        if (!uploadParentFile.exists()) {
            uploadParentFile.mkdirs();
        }
        // 定义一个文件唯一的标识位
        String uuid = IdUtil.fastSimpleUUID();
        String uurl = uuid + StrUtil.DOT + type;
        // 实际图片路径
        File uploadFile = new File(fileULoadPath + uurl);
        // 把获取到的文件存储到磁盘目录
        file.transferTo(uploadFile);
        // 文件路径
        String url = "http://localhost:9090/user/load/" + uurl;
        return Result.success("上传成功", url);
    }

    /**
     * 用户头像获取
     * @param fileUUID
     */
    @Override
    public void dowmloadImage(String fileUUID) throws IOException {
        // 根据文件的唯一标识码获取文件
        File dowmImage = new File(fileULoadPath + fileUUID);
        response.setDateHeader("Expires",0);
        response.addHeader("Pragma","no-cache");
        response.setContentType("image/jpeg");
        ServletOutputStream os = response.getOutputStream();
        os.write(FileUtil.readBytes(dowmImage));
        os.flush();
        os.close();
    }

    /**
     * 批量删除用户
     * @param ids
     * @return
     */
    @Override
    public Result deleteByIds(List<Integer> ids) {
        if (removeByIds(ids)) {
            return Result.success("批量删除用户成功！");
        }
        return Result.fail("批量删除用户失败！");
    }

    /**
     * 删除用户信息
     * @param id
     * @return
     */
    @Override
    public Result deleteById(Integer id) {
        if (removeById(id)) {
            return Result.success("删除用户信息成功！");
        }
        return Result.fail("删除用户信息失败！");
    }

    /**
     * 分页查询用户
     * @param pageNum
     * @param pageSize
     * @param nickname
     * @param number
     * @param phone
     * @param address
     * @return
     */
    @Override
    public Result pageSeach(Integer pageNum, Integer pageSize, String nickname, String number, String phone, String address) {
        IPage<User> page = new Page<>(pageNum,pageSize);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if(!"".equals(nickname)){
            queryWrapper.like("nickname",nickname);
        }
        if(!"".equals(number)){
            queryWrapper.like("number",number);
        }
        if(!"".equals(phone)){
            queryWrapper.like("phone",phone);
        }
        if(!"".equals(address)){
            queryWrapper.like("address",address);
        }
        return Result.success("分页查询成功!",page(page,queryWrapper));
    }

    /**
     * 获取用户信息
     * @param number
     * @return
     */
    @Override
    public Result UserByNumber(String number) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("number",number);
        User one = getOne(queryWrapper);
        if ( one != null){
            return Result.success("获取用户信息成功!",one);
        }
        return Result.fail("获取用户信息失败！");

    }

    @Override
    public Result editPassword(PassWordDto passWordDto) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("number",passWordDto.getNumber());
        queryWrapper.eq("password",MD5Util.inputPassToFormPass(passWordDto.getOldPassword()));
        User one = getOne(queryWrapper);
        if (one == null){
            return Result.fail("原账号密码输入错误！");
        }
        one.setPassword(MD5Util.inputPassToFormPass(passWordDto.getNewPassword()));
        saveOrUpdate(one);
        return Result.success("修改密码成功,请重新登录!");
    }


}
